package com.wang.hellohibernate.models;

import java.io.Serializable;
import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@SuppressWarnings("restriction")
@Entity
@Table(name = "persons")
@XmlRootElement(name="person")
public class Person implements Serializable
{
	private static final long serialVersionUID = 3499119918086758399L;
	
	@Id
	@GeneratedValue
	@Column(name = "id", unique=true)
	private Integer id;
	@Column(name = "firstName")
	private String firstName;
	@Column(name = "lastName")
	private String lastName;
	@Column(name = "midName")
	private String midName;
	@Column(name = "sex")
	private Integer sex;
	@Column(name = "birthday")
	private Date birthday;
	@Column(name = "idType")
	private Integer idType;
	@Column(name = "idNumber")
	private String idNumber;
	@Column(name = "homePhone")
	private String homePhone;
	@Column(name = "cellPhone")
	private String cellPhone;
	@Column(name = "workPhone")
	private String workPhone;
	@Column(name = "extension")
	private String extension;
	@Column(name = "email")
	private String email;
	@Column(name = "acceptEmail")
	private Boolean acceptEmail;
	@Column(name = "apartment")
	private String apartment;
	@Column(name = "streetNumber")
	private String streetNumber;
	@Column(name = "street")
	private String street;
	@Column(name = "city")
	private String city;
	@Column(name = "province")
	private String province;
	@Column(name = "country")
	private String country;
	@Column(name = "postCode")
	private String postCode;
	@Column(name = "createDate")
	private Date createDate;
	@Column(name = "roles")
	@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
	@JoinTable(name = "persons_roles",
			joinColumns = {@JoinColumn(name = "personid", nullable = false, updatable = false) }, 
			inverseJoinColumns = { @JoinColumn(name = "roleid", nullable = false, updatable = false) })
	private List<Role> roles;
	
	@XmlAttribute
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	@XmlElement(nillable=true, name="roles")
	public List<Role> getRoles() {
		return roles;
	}
	public void setRoles(List<Role> roles) {
		this.roles = roles;
	}
	@XmlElement(nillable=true)
	public String getFirstName() {
		return firstName;
	}
	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}
	@XmlElement(nillable=true)
	public Integer getSex()
	{
		return sex;
	}
	public void setSex(Integer sex)
	{
		this.sex = sex;
	}
	@XmlElement(nillable=true)
	public String getLastName() {
		return lastName;
	}
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	@XmlElement(nillable=true)
	public String getMidName() {
		return midName;
	}
	public void setMidName(String midName) {
		this.midName = midName;
	}
	@XmlElement(nillable=true)
	public Date getBirthday() {
		return birthday;
	}
	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}
	@XmlElement(nillable=true)
	public Integer getIdType() {
		return idType;
	}
	public void setIdType(Integer idType) {
		this.idType = idType;
	}
	@XmlElement(nillable=true)
	public String getIdNumber() {
		return idNumber;
	}
	public void setIdNumber(String idNumber) {
		this.idNumber = idNumber;
	}
	@XmlElement(nillable=true)
	public String getHomePhone() {
		return formatPhoneNumber(homePhone);
	}
	public void setHomePhone(String homePhone) {
		this.homePhone = filterPhoneNumber(homePhone);
	}
	@XmlElement(nillable=true)
	public String getCellPhone() {
		return formatPhoneNumber(cellPhone);
	}
	public void setCellPhone(String cellPhone) {
		this.cellPhone = filterPhoneNumber(cellPhone);
	}
	@XmlElement(nillable=true)
	public String getWorkPhone() {
		return formatPhoneNumber(workPhone);
	}
	public void setWorkPhone(String workPhone) {
		this.workPhone = filterPhoneNumber(workPhone);
	}
	@XmlElement(nillable=true)
	public String getExtension() {
		return extension;
	}
	public void setExtension(String extension) {
		this.extension = extension;
	}
	@XmlElement(nillable=true)
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	@XmlElement(nillable=true)
	public Boolean getAcceptEmail() {
		return acceptEmail;
	}
	public void setAcceptEmail(Boolean acceptEmail) {
		this.acceptEmail = acceptEmail;
	}
	@XmlElement(nillable=true)
	public String getApartment() {
		return apartment;
	}
	public void setApartment(String apartment) {
		this.apartment = apartment;
	}
	@XmlElement(nillable=true)
	public String getStreetNumber() {
		return streetNumber;
	}
	public void setStreetNumber(String streetNumber) {
		this.streetNumber = streetNumber;
	}
	@XmlElement(nillable=true)
	public String getStreet() {
		return street;
	}
	public void setStreet(String street) {
		this.street = street;
	}
	@XmlElement(nillable=true)
	public String getCity() {
		return city;
	}
	public void setCity(String city) {
		this.city = city;
	}
	@XmlElement(nillable=true)
	public String getProvince() {
		return province;
	}
	public void setProvince(String province) {
		this.province = province;
	}
	@XmlElement(nillable=true)
	public String getCountry() {
		return country;
	}
	public void setCountry(String country) {
		this.country = country;
	}
	@XmlElement(nillable=true)
	public String getPostCode() {
		return formatPostCode(postCode);
	}
	public void setPostCode(String postCode) {
		this.postCode = filterPostCode(postCode);
	}
	/*@XmlElement(nillable=true)
	public Long getReferrerId() {
		return referrerId;
	}
	public void setReferrerId(Long referrerId) {
		this.referrerId = referrerId;
	}*/
	@XmlElement(nillable=true)
	public Date getCreateDate() {
		return createDate;
	}
	public void setCreateDate(Date createDate) {
		this.createDate = createDate;
	}
	/*@XmlElement(nillable=true)
	public Long getHomeOrganizationId() {
		return homeOrganizationId;
	}
	public void setHomeOrganizationId(Long homeOrganizationId) {
		this.homeOrganizationId = homeOrganizationId;
	}*/
	
	private String filterPhoneNumber(String phoneNumber)
	{
		if(null == phoneNumber || 0 == phoneNumber.trim().length())
		{
			return phoneNumber;
		}

		return phoneNumber.replaceAll("[-()]", "");
	}

	private String formatPhoneNumber(String phoneNumber)
	{
		if(null == phoneNumber || 10 != phoneNumber.trim().length())
		{
			return phoneNumber;
		}

		return phoneNumber.substring(0,3) + "-" + phoneNumber.substring(3,6) + "-" + phoneNumber.substring(6);
	}
	
	
	private String filterPostCode(String postCode)
	{
		if(null == postCode || 0 == postCode.trim().length())
		{
			return postCode;
		}
		
		return postCode.replaceAll(" ", "");
	}

	private String formatPostCode(String postCode)
	{
		if(null == postCode || 0 == postCode.trim().length())
		{
			return postCode;
		}

		return postCode.substring(0,3) + " " + postCode.substring(3);
	}
	
	public boolean equals(Person person)
	{
		if(compare(person.id,this.id)
			&& compare(person.acceptEmail,this.acceptEmail)
			&& compare(person.apartment,this.apartment)
			&& compare(person.birthday,this.birthday)
			&& compare(person.cellPhone,this.cellPhone)
			&& compare(person.city,this.city)
			&& compare(person.country,this.country)
			&& compare(person.email,this.email)
			&& compare(person.extension,this.extension)
			&& compare(person.firstName,this.firstName)
			&& compare(person.homePhone,this.homePhone)
			&& compare(person.idNumber,this.idNumber)
			&& compare(person.idType,this.idType)
			&& compare(person.lastName,this.lastName)
			&& compare(person.midName,this.midName)
			&& compare(person.postCode,this.postCode)
			&& compare(person.province,this.province)
			&& compare(person.createDate,this.createDate)
			&& compare(person.street,this.street)
			&& compare(person.streetNumber,this.streetNumber))
		{
			return true;
		}

		return false;
	}
	
	private boolean compare(Object obj1, Object obj2)
	{
		if(null == obj1)
		{
			if(null == obj2)
			{
				return true;
			}
			
			return false;
		}
		else
		{
			if(null == obj2)
			{
				return false;
			}
			else
			{
				if(obj1.equals(obj2))
				{
					return true;
				}

				return false;
			}
		}
	}

	public String toString()
	{
		StringBuffer stringBuffer = new StringBuffer();
		stringBuffer.append("[ID: " + id
			+ " FIRST_NAME: " + firstName
			+ " LAST_NAME: " + lastName
			+ " MIDDLE_NAME: " + midName
			+ " BIRTHDAY: " + birthday
			+ " ID_TYPE: " + idType
			+ " ID_NUMBER: " + idNumber
			+ " HOME_PHONE: " + homePhone
			+ " CELL_PHONE: " + cellPhone
			+ " WORK_PHONE: " + workPhone
			+ "-" + extension
			+ " EMAIL: " + email
			+ " ACCEPT_EMAIL_NOTIFY: " + acceptEmail
			+ " APARTMENT: " + apartment
			+ " STREET_NUMBER: " + streetNumber
			+ " STREET: " + street
			+ " CITY: " + city
			+ " PROVINCE: " + province
			+ " COUNTRY: " + country
			+ " POST_CODE: " + postCode
			+ " CREATE_DATE: " + createDate
			+ " ROLE {");
			
		for(Role role: roles)
		{
			stringBuffer.append("[" + role.toString() + "]");
		}
		
		stringBuffer.append("}]");
			
			return stringBuffer.toString();
	}
}
